package com.yihaodian.server.servlet.rest;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yihaodian.api.search.SearchRequest;
import com.yihaodian.api.search.SearchResponse;
import com.yihaodian.api.search.SearchService;
import com.yihaodian.api.search.facet.SearchFacetSpec;
import com.yihaodian.api.search.filter.Filter;
import com.yihaodian.api.search.filter.RangeFilter;
import com.yihaodian.api.search.grouping.GroupingSpec;
import com.yihaodian.api.search.highlight.HighlightSpec;
import com.yihaodian.api.search.misc.SearchSort;
import com.yihaodian.api.search.misc.SearchSortField;

/**
 * rest/search/[indexname]/?q=xxx
 * 
 */
public class SearchServlet extends AbstractServlet {

	public static final String write_type_json = "json";
	public static final String write_type_jsp = "jsp";

	public static final String sperator = ";";
	public static final String param_write_type = "wt";
	public static final String param_query = "q";
	public static final String param_sort = "sort";
	public static final String param_hightlight = "hl";
	public static final String param_facet = "ft";
	public static final String param_grouping = "gp";
	public static final String param_price_range = "p";
	public static final String flag_grouping = "flag_gp";

	SearchRequest getSearchRequest(HttpServletRequest req) {
		String index = super.getIndexName(req);
		String query = req.getParameter(param_query);

		SearchRequest searchReq = new SearchRequest(index, query);

		Filter filter = getFilter(req);
		searchReq.setFilter(filter);
		SearchSort sort = getSort(req);
		searchReq.setSort(sort);
		HighlightSpec[] hl = getHightlight(req);
		searchReq.setHighlightSpecs(hl);
		Map<String, SearchFacetSpec> facet = getFacet(req);
		searchReq.setFacetSpecMap(facet);
		GroupingSpec groupingSpec = getGrouping(req);
		searchReq.setGroupingSpec(groupingSpec);

		return searchReq;
	}
	
	Filter getFilter(HttpServletRequest req) {
		String s = req.getParameter(param_price_range);
		if (s == null)
			return null;
		
		String[] ranges = s.split(",");
		if (ranges.length != 2) {
			return null;
		}
		RangeFilter f = new RangeFilter("sale", Integer.parseInt(ranges[0]), 
				Integer.parseInt(ranges[1]), true, true);
		return f;
	}

	SearchSort getSort(HttpServletRequest req) {
		String s = req.getParameter(param_sort);
		if (s == null)
			return null;

		String[] split = s.split(sperator);
		boolean reverse = false;
		SearchSortField[] fields = new SearchSortField[split.length];
		for (int i = 0; i < split.length; i++) {
			String[] ss = split[i].split(" ");
			reverse = true;
			if (ss.length > 1 && ("asc".equals(ss[1])))
				reverse = false;
			fields[i] = new SearchSortField(ss[0], reverse);
		}

		return new SearchSort(fields);
	}

	HighlightSpec[] getHightlight(HttpServletRequest req) {
		String hl = req.getParameter(param_hightlight);
		if (hl == null)
			return null;

		String[] splits = hl.split(sperator);
		HighlightSpec[] highlightSpec = new HighlightSpec[splits.length];
		for (int i = 0; i < splits.length; i++) {
			highlightSpec[i] = new HighlightSpec(splits[i]);
		}

		return highlightSpec;
	}

	Map<String, SearchFacetSpec> getFacet(HttpServletRequest req) {
		String facet = req.getParameter(param_facet);
		if (facet == null)
			return null;

		String[] splits = facet.split(sperator);
		Map<String, SearchFacetSpec> facetMap = new HashMap<String, SearchFacetSpec>();
		for (String s : splits) {
			SearchFacetSpec searchFacet = new SearchFacetSpec();
			searchFacet.setOrderBy(SearchFacetSpec.ORDER_LABEL_ASC);
			facetMap.put(s, searchFacet);
		}

		return facetMap;
	}

	GroupingSpec getGrouping(HttpServletRequest req) {
		String group = req.getParameter(param_grouping);
		if (group == null)
			return null;

		GroupingSpec groupingSpec = new GroupingSpec();
		groupingSpec.setGroupingTerm(group);

		return groupingSpec;
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		SearchRequest searchReq = getSearchRequest(req);
		SearchResponse searchResp = (SearchResponse) brokerService.execute(searchReq);

		String wt = req.getParameter(param_write_type);
		if (write_type_jsp.equals(wt)) {
			String indexName = searchReq.getIndexName();
			RequestDispatcher rd = req.getRequestDispatcher("/jsp/" + indexName
					+ "/search.jsp");
			if (searchReq.getGroupingSpec() != null) {
				req.setAttribute(flag_grouping, 1);
			}

			req.setAttribute("ht", req.getParameter(param_hightlight));
			req.setAttribute("sr", searchResp);
			req.setAttribute("keyword", searchReq.getQuerySyntax());
			rd.forward(req, resp);
		} else {
			super.respJson(req, resp, searchResp);
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}

	@Override
	public void init() throws ServletException {
		super.init();
	}
}
